package com.sherlocky.learning.java8.defaultmethod;

/**
 * Java 8 新增了接口的默认方法。
 *      简单说，默认方法就是接口可以有实现方法，而且不需要实现类去实现其方法。
 * 我们只需在方法名前面加个default关键字即可实现默认方法。
 *
 * <p>为什么要有这个特性？
 *
 * 首先，之前的接口是个双刃剑，好处是面向抽象而不是面向具体编程，缺陷是，当需要修改接口时候，需要修改全部实现该接口的类，目前的java   8之前的集合框架没有foreach方法，通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。
 * 然而，对于已经发布的版本，是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。
 * 他们的目的是为了解决接口的修改与现有的实现不兼容的问题。</p>
 *
 * - 1.默认方法就是接口可以有实现方法
 * - 2.【静态默认方法】接口可以声明（并且可以提供实现）静态方法
 *
 * 和抽象类的区别：
 * - 1.一个类只能继承一个抽象类；但是一个类可以实现多个接口。
 * - 2.抽象类有实例变量，而接口只能有类变量。
 *
 * 多继承关系的三条规则：
 *
 * - 类中的方法优先级最高，类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。
 * - 如果第一条无法判断，那么子接口的优先级更高：方法签名相同时，优先选择拥有最具体实现的默认方法的接口， 即如果B继承了A，那么B就比A更加具体。
 * - 最后，如果还是无法判断，继承了多个接口的类必须通过显式覆盖和调用期望的方法， 显式地选择使用哪一个默认方法的实现。
 *   比如：InterfaceA.super.someMethod() 这样显式调用
 *
 */
public class DefaultmethodSample {
    public static void main(String[] args) {
        Vehicle vehicle = new Car2();
        vehicle.print();
    }
}

interface Vehicle {
    default void print(){
        System.out.println("我是一辆车!");
    }
    // 静态方法
    static void blowHorn() {
        System.out.println("按喇叭!!!");
    }
}

interface FourWheeler {
    default void print(){
        System.out.println("我是一辆四轮车!");
    }
}

// 一个接口有默认方法，考虑这样的情况，一个类实现了多个接口，且这些接口有相同的默认方法,可以这么解决
class Car implements Vehicle {
    // 创建自己的默认方法，来覆盖重写接口的默认方法：
    @Override
    public void print() {
        System.out.println("我是一辆四轮汽车!");
    }
}

// 还可以这么解决
class Car2 implements Vehicle, FourWheeler {
    // 使用 super 来调用指定接口的默认方法：
    @Override
    public void print() {
        Vehicle.super.print();
        FourWheeler.super.print();
        Vehicle.blowHorn();
        System.out.println("我是一辆汽车!");
    }
}
